package com.base.themvx.v

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.viewbinding.ViewBinding
import com.base.themvx.action.ClickAction
import com.base.themvx.defNonSyncLazy
import com.base.themvx.vm.BaseViewModel
import java.lang.reflect.ParameterizedType

/**
 * <p>
 *     通用的基础 的[V]视图层, 简化 ViewBinding、ViewModel
 * </p>
 *
 * @author Kingbo
 * @date 2025/4/19
 */
abstract class BaseViewVmDelegate<VB : ViewBinding, VM : BaseViewModel>(context: Context) :
    BaseViewDelegate(context), ClickAction {

    override fun onCreateView(container: ViewGroup?, savedInstanceState: Bundle?): View? {
        configImmersiveWindow()
        return super.onCreateView(container, savedInstanceState)
    }

    override fun provideVLayoutRes() = 0

    override fun provideTheDelegateView(): View? {
        val binding = getViewBinding()
        if (binding != null) {
            mBinding = binding
            return binding.root
        }
        getLayoutViewSelf()?.let {
            return it
        }
        logE(TAG, "getLayoutViewSelf() return null, 无法获取布局View")
        return FrameLayout(mContext)
    }

    // --------------------------------------------------------- @ abstract

    protected lateinit var mBinding: VB

    protected val mViewModel: VM by defNonSyncLazy { getViewModel() }

    /**
     * 获取ViewBinding（手动初始化）
     */
    open fun getViewBinding(): VB? = null

    /**
     * 获取ViewModel
     */
    abstract fun getViewModel(): VM

    override fun onClick(view: View?) {
        // nothing
    }

    // -------------------------------------------------------- @ private

    @Suppress("UNCHECKED_CAST")
    private fun getLayoutViewSelf(): View? {
        if (rootView == null) {
            val type = javaClass.genericSuperclass as ParameterizedType
            val vbClass = type.actualTypeArguments[0] as Class<VB>
            val method = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
            method.invoke(this, fetchLayoutInflater())?.let {
                mBinding = it as VB
                rootView = mBinding.root
            }
        }
        return rootView
    }

}